<template>
    <div :style="{ width: leftWidth }" class="left-tree-wrap">
        <flexbox justify="flex-start" direction="column" v-if="isCollasped" style="height: calc(100vh - 88px)">
            <div style="margin: 2px 0 12px 0">
                <HIcon icon="DoubleRightOutlined" @click="handleCollasped" />
            </div>
            <span>产</span>
            <span>品</span>
            <span>线</span>
        </flexbox>
        <div style="position: relative" v-else>
            <a-tabs v-model:activeKey="activeKey" @change="handleTabChange">
                <a-tab-pane :tab="item.name" :key="item.value" v-for="item of gradeTabList" />
            </a-tabs>
            <a-input-search v-model:value="searchValue" style="margin-bottom: 8px" placeholder="请输入搜索内容" @search="handleSearch" />
            <div style="height: calc(100vh - 176px); overflow: hidden;scroll;position:relative">
                <a-spin :spinning="loading" style="position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%)" />
                <a-tree
                    :blockNode="true"
                    :tree-data="treeData"
                    v-model:expandedKeys="expandedKeys"
                    v-model:selectedKeys="selectedKeys"
                    :replaceFields="{ children: 'subNodes', key: 'id', title: 'catalogName' }"
                    @select="handleSelectTreeNode"
                    v-if="treeData.length"
                >
                    <template v-slot:title="{ catalogName, catalogType, count }">
                        <flexbox class="title-wrap">
                            <a-tag :class="`tag${catalogType}`" v-if="+catalogType >= 0">{{ $filters.catalogTypeFilter(catalogType) }}</a-tag>
                            <span class="text-bre1" v-if="searchValue && catalogName.indexOf(searchValue) > -1">
                                {{ catalogName.substr(0, catalogName.indexOf(searchValue)) }}
                                <span style="color: #f50">{{ searchValue }}</span>
                                {{ catalogName.substr(catalogName.indexOf(searchValue) + searchValue.length) }}
                            </span>
                            <span class="text-bre1" v-else>{{ catalogName }} {{ +catalogType < 2 ? `(${count})` : '' }}</span>
                        </flexbox>
                    </template>
                </a-tree>
            </div>
            <div style="position: absolute; right: 6px; top: 2px; cursor: pointer">
                <HIcon icon="DoubleLeftOutlined" @click="handleCollasped" />
            </div>
        </div>

        <div class="moveBtn" v-move="updateWidth" :width="290" v-if="!isCollasped" />
    </div>
</template>

<script lang="ts">
import api from '@/api';
import { deepClone } from '@/utils/util';
import { getChildNodes } from '@/utils/tree';
import { defineComponent, ref, unref, reactive, toRefs } from 'vue';
export default defineComponent({
    props: {
        // 层级限制
        levelLimit: {
            type: Number,
            default: 2
        }
    },
    emits: ['change', 'updateWidth'],
    setup(props, { emit }) {
        const state = reactive<any>({
            allTreeData: [],
            treeData: [],
            autoExpandParent: false,
            searchValue: '',
            expandedKeys: [],
            allExpandedKeys: [],
            selectedKeys: [1],
            leftWidth: '290px',
            firstLeftWidth: '290px',
            gradeTabList: [
                { name: '全部', value: 'all' },
                { name: 'L1', value: 'L1' },
                { name: 'L2', value: 'L2' },
                { name: 'L3', value: 'L3' },
                { name: 'L4', value: 'L4' }
            ],
            activeKey: 'all',
            isCollasped: false,
            loading: true
        });
        const transformDataByFlatProperty = (data, fields = { keyField: 'node', childrenField: 'subNodes' }) => {
            const { keyField, childrenField } = fields;
            data.forEach((item, index) => {
                data[index] = {
                    ...data[index],
                    ...data[index][keyField],
                    catalogName: data[index][keyField].catalogName
                };
                if (item[childrenField] && item[childrenField].length && +item.node.catalogType < props.levelLimit) {
                    state.expandedKeys.push(item.id);
                    data[index][childrenField] = transformDataByFlatProperty(item[childrenField], fields);
                } else {
                    data[index][childrenField] = null;
                }
            });
            return data;
        };
        const getTreeCount = (data, fields = { keyField: 'node', childrenField: 'subNodes' }) => {
            const { childrenField } = fields;
            data.forEach((item, index) => {
                const allNodes = getChildNodes(item);
                data[index] = {
                    ...data[index],
                    count: allNodes.length
                };
                if (item[childrenField] && item[childrenField].length && +item.node.catalogType < props.levelLimit) {
                    data[index][childrenField] = getTreeCount(item[childrenField], fields);
                } else {
                    data[index][childrenField] = null;
                }
            });
            return data;
        };
        const updateWidth = (val) => {
            state.leftWidth = val;
            emit('updateWidth', val);
        };
        const formatData = (arr) => {
            const newArr: any = [];
            arr.forEach((item: any) => {
                // 判断条件，包含大小写转换，便于查找英文
                if (item['catalogName'].toUpperCase().indexOf(state.searchValue.toUpperCase()) > -1) {
                    newArr.push(item);
                } else {
                    if (item.subNodes && item.subNodes.length > 0) {
                        const redata = formatData(item.subNodes);
                        if (redata && redata.length > 0) {
                            const obj = {
                                ...item,
                                subNodes: redata
                            };
                            state.expandedKeys.push(item.id);
                            newArr.push(obj);
                        }
                    }
                }
            });
            return newArr;
        };
        const handleSearch = () => {
            if (state.searchValue) {
                state.expandedKeys = [];
                const data: any = deepClone(formatData(state.allTreeData));
                if (data.length) {
                    state.treeData = getTreeCount(deepClone(data));
                } else {
                    state.treeData = [];
                    state.expandedKeys = [];
                }
            } else {
                state.expandedKeys = state.allExpandedKeys;
                state.treeData = deepClone(state.allTreeData);
            }
        };
        const handleSelectTreeNode = (val, { node }) => {
            emit('change', node.dataRef);
        };
        const handleTabChange = (val) => {
            getTreeData();
        };
        const handleCollasped = () => {
            state.isCollasped = !state.isCollasped;
            if (state.isCollasped) {
                updateWidth('40px');
            } else {
                updateWidth(state.firstLeftWidth);
            }
        };
        const getTreeData = async () => {
            state.loading = true;
            let query: any = {
                needModule: 0,
                tenantId: 'teep-pmp'
            };
            if (state.activeKey !== 'all') {
                query = {
                    ...query,
                    productGrade: state.activeKey
                };
            }
            const { success, moule } = await api.acmdbModel.getTree(query);
            state.loading = false;
            if (success) {
                const treeObj = JSON.parse(moule);
                if (treeObj.productLineTree) {
                    const obj = [
                        {
                            id: 1,
                            node: {
                                catalogName: '全部',
                                catalogType: -1
                            },
                            subNodes: [...treeObj.productLineTree]
                        }
                    ];
                    state.expandedKeys = [];
                    const arr = transformDataByFlatProperty(deepClone(obj));
                    // 先渲染树
                    state.treeData = arr;
                    // 获取所有展开树
                    state.allExpandedKeys = deepClone(state.expandedKeys);
                    // 获取数量更新
                    state.allTreeData = getTreeCount(deepClone(state.treeData));
                    state.treeData = deepClone(state.allTreeData);
                }
            }
        };
        getTreeData();
        return {
            ...toRefs(state),
            updateWidth,
            handleSearch,
            handleTabChange,
            handleSelectTreeNode,
            handleCollasped
        };
    }
});
</script>

<style scoped lang="less">
.left-tree-wrap {
    flex-shrink: 0;
    padding: 12px;
    background: #fff;
    position: relative;
    border-right: 1px solid rgb(231, 231, 231);
    .tag0 {
        background: rgba(35, 89, 221, 0.12);
        border-color: rgba(35, 89, 221, 0.12);
        color: #2359dd;
    }
    .tag1 {
        background: rgba(95, 191, 168, 0.14);
        border-color: rgba(95, 191, 168, 0.14);
        color: #5fbea8;
    }
    .tag2 {
        background: #edeff3;
        border-color: #edeff3;
        color: rgba(23, 35, 61, 0.65);
    }
    /* 拖动条 */
    .moveBtn {
        height: 100%;
        width: 6px;
        /* opacity: 0; */
        position: absolute;
        right: 0px;
        top: 0;
        cursor: col-resize;
    }
    ::v-deep(.ant-tabs-nav .ant-tabs-tab) {
        margin-right: 0 !important;
        padding-top: 2px !important;
    }
    ::v-deep(.ant-tree li .ant-tree-node-content-wrapper.ant-tree-node-selected) {
        background-color: #ecf2fe !important;
    }
    ::v-deep(.ant-tree) {
        overflow-y: auto;
        overflow-x: hidden;
        height: 100%;
        margin-bottom: 18px !important;
        scrollbar-width: none;
    }
}
</style>